#pragma once

#include "CDIAUDTObj.h"
#include "cmemspace.h"

#define btPointer (btHresult+1)
class CBaseType
{
class CTypeSizeMap
{
public:
	CTypeSizeMap();
public:
	DWORD operator[](int iType){return m_map[iType];};
public:
	CExceptMap<int, DWORD>	m_map;
};

public:
	CBaseType();

public:
	static DWORD SizeofBaseType(int iType){ return ms_mapTypeSize[iType];};
	static BOOL Strm2CStr(CString* pcstr, int iType, BYTE* pbStrm);
	static BOOL CStr2Strm(int iType, CString* pcstr, BYTE* pbStrm);

private:
	static CTypeSizeMap	ms_mapTypeSize;
};

class CUDTWtchObj;

class IUDTWtchEnum
{
public:
	virtual ~IUDTWtchEnum(){};

public:
	virtual bool Next( CUDTWtchObj** ppObj, IMemSpace* pIMem=NULL)=0;
	virtual void Reset()=0;
};

class CUDTWtchObj
{
friend class CUDTWtchObjEnum;

public:
const static DWORD INVALID_ADDR=(DWORD)(-1);

public:
	// construct the UDTObj with out udtdata
	CUDTWtchObj(IDiaSymbol*psymbType, TCHAR* pszName, DWORD dwBaseAddr=NULL)
				:m_pUDTObj(new CUDTObj(psymbType, pszName)), m_pbVal(NULL)
	{InitConstructHlep(dwBaseAddr);};

	CUDTWtchObj(IDiaSymbol*psymbData, DWORD dwBaseAddr=NULL)
		:m_pUDTObj(new CUDTObj(psymbData)), m_pbVal(NULL)
	{InitConstructHlep(dwBaseAddr);};

	CUDTWtchObj(CUDTObj* pUDTObj, DWORD dwBaseAddr=NULL)
				:m_pUDTObj(pUDTObj), m_pbVal(NULL)
	{InitConstructHlep(dwBaseAddr);};

	// second init stat
	BOOL InitVal(IMemSpace* pIMem);

	~CUDTWtchObj(); 
private:
	void InitConstructHlep(DWORD dwBaseAddr);

public:
	bool EnumChild(IUDTWtchEnum** ppEnum, BOOL fExpandPtr=FALSE);

public:
	void SetBaseAddr(DWORD dwBaseAddr);
	DWORD GetAddr(){return m_dwAddr;};

	BOOL GetVal(int* piType, BYTE* pbBuf, IMemSpace* pIMem=NULL);
	BOOL SetVal(int iType, BYTE* pbBuf, IMemSpace* pIMem=NULL);

// stub for udtobj
public:
	void GetName(CString* pstr){m_pUDTObj->GetName(pstr);};
	void GetType(CString* pstr){m_pUDTObj->GetType(pstr);}; 
	DWORD GetSize(){return m_pUDTObj->GetSize();}; 
	DWORD GetOffset(){return m_pUDTObj->GetOffset();}; 
	BOOL IsPtr(){return m_pUDTObj->IsPtr();};
	BOOL Is_static(){return m_pUDTObj->Is_static();};
	BOOL IsBaseType(DWORD* pdwBaseType=NULL){return m_pUDTObj->IsBaseType(pdwBaseType);};
	int GetWatchBaseType(){return m_iBaseType;};
	BOOL IsBit(){return (btBit==m_iBaseType)?TRUE:FALSE;};
	DWORD GetBitPos(){return m_dwBitPos;};
	DWORD GetBitLen(){return m_dwBitLen;};

private:
	CUDTObj* m_pUDTObj;
	DWORD m_dwAddr;
	int m_iBaseType;	// BasicType or pointer=BasicType+1
	DWORD m_dwSize;
	BYTE*  m_pbVal;
	// for bit struct
	DWORD m_dwBitPos;
	DWORD m_dwBitLen;
};

class CUDTWtchObjEnum: public IUDTWtchEnum
{
public:
	CUDTWtchObjEnum(IUDTEnum* pUDTEnum, CUDTWtchObj* pWtchObj, BOOL fExpandPtr=FALSE)
					:m_pUDTEnum(pUDTEnum), m_pWtchObj(pWtchObj), m_fExpandPtr(fExpandPtr)
	{};
	virtual ~CUDTWtchObjEnum();

public:
	virtual bool Next( CUDTWtchObj** ppObj, IMemSpace* pIMem=NULL);
	virtual void Reset(){m_pUDTEnum->Reset();};

private:
	IUDTEnum* m_pUDTEnum;
	CUDTWtchObj* m_pWtchObj;
	BOOL m_fExpandPtr;
};
